﻿using Wabo.Dal.Interface;
using Wabo.Util;
using Wabo.Web.Areas.Manager.Core;
using Wabo.Web.Areas.Manager.Core.Attributes;
using System.Web.Mvc;
using Wabo.Web.Areas.Manager.ViewModels.User;
using System;
using System.Collections.Generic;
using System.Linq;
using Wabo.Web.Resources;
using PagedList;
using PagedList.Mvc;

namespace Wabo.Web.Areas.Manager.Controllers
{
    [UserAuthorized]
    public class UserController : WaboController
    {
            
        // User profile settings
        public ActionResult Settings()
        {
            var model = new UserSettingsViewModel(AuthorizedUser);
            LogEvent(LogOperation.View,"Profile Page");
            return View(model);
        }

        [HttpPost]
        public ActionResult Settings(UserSettingsViewModel model)
        {
            if (ModelState.IsValid)
            {
                Dal.User usr = UserContext.Get(AuthorizedUser.id);
                usr.name = model.FirstName;
                usr.last_name = model.LastName;
                if (!string.IsNullOrEmpty(model.Password))
                    usr.password = UserContext.CreateHashedPassword(usr.salt, model.Password);
                UserContext.Update(usr);
                SessionManager.Authorize(usr);
                LogEvent(LogOperation.Modify, "Profile settings");
                AddActionMessageToken( Messages.DISP_ProfileSettingsUpdated );                
                return RedirectToAction("Index", "Dashboard");
            }
            return View(model);
        }

        // List messages
        public ActionResult MailBox(int id = 0 /* 0:All 1:Unread 2:Sent */, int page = 1)
        {
            // check for invalid parameters and fix
            if (page < 1) page = 1;
            if (id < 0 || id > 2) id = 0;

            var model = new UserMessagesViewModel();
            model.CurrentMailBox = id;
            switch (id)
            {
                case 0:
                    model.Messages = UserMessages.GetAllRootMessagesOfUser(AuthorizedUser).OrderByDescending(m => m.send_date);
                    model.CurrentMailBoxTitle = Messages.DISP_AllMessages;                    
                    break;
                case 1:
                    model.Messages = UserMessages.GetUnreadRootMessagesOfUser(AuthorizedUser).OrderByDescending(m => m.send_date);
                    model.CurrentMailBoxTitle = Messages.DISP_UnreadMessages;
                    break;
                case 2:
                    model.Messages = UserMessages.GetSentMessagesOfUser(AuthorizedUser).OrderByDescending(m => m.send_date);
                    model.CurrentMailBoxTitle = Messages.DISP_SentMessages;
                    break;
                default:
                    model.Messages = UserMessages.GetAllRootMessagesOfUser(AuthorizedUser).OrderByDescending(m => m.send_date);
                    model.CurrentMailBoxTitle = Messages.DISP_AllMessages;
                    break;
            }
            model.Messages = model.Messages.ToPagedList(page, SystemSettingsContext.LogViewerItemCountPerPage);
            model.Message = new ComposeMessageViewModel();
            LogEvent(LogOperation.View, "User Messages");
            return View(model);
        }
        
        // compose new message or reply to message 
        public ActionResult Compose(int id =-1)
        {
            ViewBag.Users = UserContext.Users.OrderBy(u => u.name).OrderBy(u => u.last_name)
                .Select(u => new SelectListItem
                {
                    Value = u.id.ToString(),
                    Text = u.name + " " + u.last_name
                }).ToList();
            var model = new ComposeMessageViewModel();
            model.NavigationBackUrl = Request.UrlReferrer.AbsoluteUri;
            var sourceMessage = UserMessages.GetMessageById(id);
            if( sourceMessage != null )
            {
                // replying
                model.MessageTitle = String.Format("RE:{0}",sourceMessage.message_title );
                model.ToUser = sourceMessage.from_user;                
                model.MessageBody = "---------------------------------------" + sourceMessage.message_body;
            }            
            return View(model);
        }

        [HttpPost]
        public ActionResult Compose(ComposeMessageViewModel model)
        {
            Dal.Message msg = new Dal.Message();
            msg.message_body = model.MessageBody;
            msg.message_title = model.MessageTitle;
            msg.from_user = AuthorizedUser.id;
            msg.to_user = model.ToUser;
            msg.is_read = false;
            msg.send_date = DateTime.Now;

            UserMessages.SendMessage(msg);
            LogEvent(LogOperation.Create, String.Format("User {0} sent message to {1}", AuthorizedUser.username,UserContext.Get(model.ToUser).username));
            //Redirect to sent messages
            return RedirectToAction("MailBox", new { id = 1 });    
        }

        // Display Message
        public ActionResult ReadMessage(int id = -1/* MessageId */ )
        {            
            var sourceMessage = UserMessages.GetMessageById(id);
            if (sourceMessage == null)
            {
                return RedirectToAction("MailBox");
            }
            if (sourceMessage.to_user != AuthorizedUser.id && sourceMessage.from_user != AuthorizedUser.id )
            {
                return RedirectToAction("MailBox");
            }
            if( sourceMessage.to_user == AuthorizedUser.id )
                UserMessages.MarkMessageAsRead((long) id);
            
            ReadMessageViewModel model = new ReadMessageViewModel()
            {
                MessageBody  = sourceMessage.message_body,
                MessageTitle = sourceMessage.message_title,
                MessageId    = sourceMessage.id,
                FromUser     = sourceMessage.FromUser.username,
                ToUser       = sourceMessage.ToUser.username,
                IsSentMail   = sourceMessage.FromUser.id == AuthorizedUser.id,
                NavigationBackUrl = Request.UrlReferrer.AbsoluteUri
            };

            return View(model);

        }

        public ActionResult MarkAsUnread(int id = -1/* MessageId */ )
        {
            var sourceMessage = UserMessages.GetMessageById(id);
            if (sourceMessage == null)
            {
                return RedirectToAction("MailBox");
            }
            if (sourceMessage.to_user != AuthorizedUser.id)
            {
                return RedirectToAction("MailBox");
            }
            UserMessages.MarkMessageAsUnread( sourceMessage.id);
            //redirect to unread messages
            return RedirectToAction("MailBox", new { id = 1 });

        }

        [ModuleListPermission]
        public ActionResult Index()
        {

            bool userHasWritePermission = ModuleContext.UserCanWrite( AuthorizedUser, ModuleContext.Get("User") );
            bool userHasDeletePermission = ModuleContext.UserCanDelete(AuthorizedUser, ModuleContext.Get("User"));
            var model = new UserListViewModel
            {
                CanWrite =  userHasWritePermission,
                CanDelete = userHasDeletePermission
            };            
            foreach (Dal.User u in UserContext.Users)
            {
                model.Users.Add(
                    new UserListItem
                    {                        
                        User = u
                    }
                );
            }
            LogEvent(LogOperation.View);
            object messageTokenObject = GetActionMessageToken(); 
            if( messageTokenObject != null ) 
            {
                AddInfoMessage( (string) messageTokenObject );
                ClearActionMessageToken();
            }
            return View(model);
        }
        [ModuleWritePermission]
        public ActionResult Create()
        {
            LogEvent(LogOperation.View);
            return View();
        }
        [HttpPost]
        [ModuleWritePermission]
        public ActionResult Create(Dal.User model)
        {      
            if (ModelState.IsValid)
            {
                model.salt = Crypto.GenerateSalt();
                model.password = UserContext.CreateHashedPassword(model.salt, model.password);
                UserContext.Add(ref model);
                LogEvent(LogOperation.Create,String.Format("Username:{0}",model.username) );
                AddActionMessageToken(String.Format(Messages.DISP_UserCreatedInfoMessage, model.username));                
                return RedirectToAction("Index");
            }
            return View(model);
        }

        [ModuleWritePermission]
        public ActionResult Edit(long id )
        {
            Dal.User usr = UserContext.Get(id);
            if (usr != null)
            {
                usr.password = "";
                LogEvent(LogOperation.View, String.Format("Username:{0}", usr.username));
                return View(usr);
            }
            return RedirectToAction("Index", "User");
        }

        [HttpPost]
        [ModuleWritePermission]
        public ActionResult Edit(Dal.User model)
        {
            ModelState.Remove("password");
            if( ModelState.IsValid)
            {
                Dal.User usr = UserContext.Get(model.id);                
                model.salt = usr.salt;
                model.password = !string.IsNullOrEmpty(model.password) ? UserContext.CreateHashedPassword(model.salt, model.password) : usr.password;
                UserContext.Update(model);
                LogEvent(LogOperation.Modify,String.Format("Username:{0}",model.username));
                // If current user updated his own data , reauthorize so profile information
                // does not display the old values.
                if (usr.id == AuthorizedUser.id)
                    SessionManager.Authorize(usr);
                AddActionMessageToken( String.Format(Messages.DISP_UserUpdatedInfoMessage,model.username));            
                return RedirectToAction("Index", "User");
            }
            return View(model);
        }

        [ModuleDeletePermission]
        public ActionResult Delete(long id)
        {
            var model = UserContext.Get(id);
            LogEvent(LogOperation.View,String.Format("Username:{0}",model.username));
            return View(model);
        }

        [HttpPost]
        [ModuleDeletePermission]        
        public ActionResult Delete(Dal.User model)
        {
            string userName = UserContext.Get(model.id).username;
            LogEvent(LogOperation.Delete,String.Format("Username:{0}",userName));
            AddActionMessageToken( String.Format(Messages.DISP_UserDeletedInfoMessage, userName));            
            UserContext.Remove(model.id);            
            return RedirectToAction("Index");
        }
    }
}
